meta_block = {
  __call = function(self, tuple)
    local k,v
    for k,v in ipairs(self.predicates) do
      local t = v.action(self.properties,tuple)
      if t then
        local link,call
        for link,call in ipairs(v.links) do 
          call(t)
        end
      end
    end
  end,
  link = function(self, port, block)
    local out = self.predicates[port]
    if out then
      out.links = out.links or {}
      out.links[#out.links+1] = block
    end
  end,
  unlink = function(self, port, block)
    local out = self.predicates[port]
    if out then
      local k,v 
      for k,v in ipairs(out.links) do 
        if v == block then
          table.remove(out.links,k)
        end
      end
    end
  end,  
  __index = function(t,k)
    return getmetatable(t)[k]
  end,
}

block = function (predicates,properties)
  local b = {
      predicates = {},
      properties = {}, --Property values for the block
    }
  local k,v
  for k,v in ipairs(predicates) do
    b.predicates[k]={ action = v, links ={} }
  end
  for k,v in pairs(properties) do
    b.properties[k]=v
  end      
  setmetatable(b,meta_block)
  return b
end

b1 = block({function(properties,tuple) if tuple ~= 1 then return tuple+properties.a end end},{a=1})
b2 = block({print},{})

b1(1)
b1(2)
b2(1)
b2(2)
b1:link(1,b2)
b1(1)
b1(2)
b2(1)
b2(2)
b1:unlink(1,b2)
b1(1)
b1(2)
b2(1)
b2(2)

entry=1
open = true
closed = false
auctionboard={}
auctionboard.board = {}
auctionboard.place = function(self, item)
  self.board[item] = {status=open, bid = 0}
end
auctionboard.bid = function(self,who,item,bid)
  local i = self.board[item]
  if (i.status==open) then
    if (i.bid or 0) < bid then
      i.bidder = who
      i.status = closed
    end
  end
end
auctionboard.peek = function(self, item)
  return self.board[item].status,self.board[item].bid,self.board[item].bidder
end
auctionboard:place(1)
auctionboard:bid("rob",1,100)
print(auctionboard:peek(1))


--list of blocks
--list of links between blocks

--instantiate all blocks
--connect blocks with links
block{name,class,x,y,properties}
link{nameA[1],nameB}

count = 0
callbacks = {
    StartElement = function (parser, name, attributes)
        io.write("+ ", string.rep(" ", count), name, attributes["param"],"\n")
        count = count + 1
    end,
    Comment = function(parser, comment)
        io.write("! ", string.rep(" ", count), comment,"\n")
    end,
    EndElement = function (parser, name)
        count = count - 1
        io.write("- ", string.rep(" ", count), name, "\n")
    end
}

p = lxp.new(callbacks)

for l in io.lines() do  -- iterate lines
    p:parse(l)          -- parses the line
    p:parse("\n")       -- parses the end of line
end

<xd:ana param="123">
<!--  hello -->
</xd:ana>

p:parse()               -- finishes the document
p:close()               -- closes the parser
